/****************************************************************
 * <strong>MFSqlWhere基类</strong>
 *
 * <p>
 * MFSqlWhere基类
 * </p>
 *
 * @author AndyZhang 2011 cnet2001@163.com
 * @version 0.1
 * ToDo:
 ***************************************************************/

package com.thinkwide.data.ormapping.sql;

import com.thinkwide.data.core.MFString;
import com.thinkwide.data.core.MFStringBuilder;
import org.apache.commons.collections4.map.LinkedMap;

import java.util.Date;
import java.util.Map;

public class MFSqlWhere {
    private Map<String, MFSqlWhereType> whereList;

    public MFSqlWhere() {
        whereList = new LinkedMap();
    }

    public MFSqlWhere addLBracket() {
        whereList.put("", MFSqlWhereType.LBRACKET);
        return this;
    }

    public MFSqlWhere addRBracket() {
        whereList.put("", MFSqlWhereType.RBRACKET);
        return this;
    }

    public MFSqlWhere addOr(String field, Object arg, MFSqlWhereType whereType) throws Exception {
        whereList.put(getWhere(field, arg, whereType), MFSqlWhereType.OR);
        return this;
    }

    public MFSqlWhere addOrNotNe(String field, Object arg, MFSqlWhereType whereType) throws Exception {
        String str = MFString.nullToString(arg);
        if (MFString.notNullOrEmpty(str)) {
            whereList.put(getWhere(field, arg, whereType), MFSqlWhereType.OR);
        }
        return this;
    }

    public MFSqlWhere addAndNotNe(String field, Object arg, MFSqlWhereType whereType) throws Exception {
        String str = MFString.nullToString(arg);
        if (MFString.notNullOrEmpty(str)) {
            whereList.put(getWhere(field, arg, whereType), MFSqlWhereType.AND);
        }
        return this;
    }

    public MFSqlWhere addAnd(String field, Object arg, MFSqlWhereType whereType) throws Exception {
        whereList.put(getWhere(field, arg, whereType), MFSqlWhereType.AND);
        return this;
    }

    public String getWhere(String field, Object arg, MFSqlWhereType whereType) throws Exception {
        if (arg instanceof String || arg instanceof Date) {
            switch (whereType) {
                case EQ:
                    return String.format("%s %s '%s'", field, MFSqlBase.EQUAL, arg);
                case LT:
                    return String.format("%s %s '%s'", field, MFSqlBase.LESS, arg);
                case GT:
                    return String.format("%s %s '%s'", field, MFSqlBase.MORE, arg);
                case LE:
                    return String.format("%s %s '%s'", field, MFSqlBase.LESS + MFSqlBase.EQUAL, arg);
                case GE:
                    return String.format("%s %s '%s'", field, MFSqlBase.MORE + MFSqlBase.EQUAL, arg);
                case LIKE:
                    return String.format("%s %s '%s'", field, MFSqlBase.LIKE, arg);
                case LIKE_ALL:
                    return String.format("%s %s '%%%s%%'", field, MFSqlBase.LIKE, arg);
                case LIKE_LEFT:
                    return String.format("%s %s '%%%s'", field, MFSqlBase.LIKE, arg);
                case LIKE_RIGHT:
                    return String.format("%s %s '%s%%'", field, MFSqlBase.LIKE, arg);
                case NOT_LIKE:
                    return String.format("%s %s '%s%%'", field, MFSqlBase.LIKE, arg);
                case IN:
                    return String.format("%s %s '%%%s%%'", field, MFSqlBase.LIKE, arg);
                case NOT_IN:
                    return String.format("%s %s '%%%s%%'", field, MFSqlBase.LIKE, arg);
            }
            return String.format("'%s'", arg);
        } else {
            switch (whereType) {
                case EQ:
                    return String.format("%s %s %s", field, MFSqlBase.EQUAL, arg);
                case LT:
                    return String.format("%s %s %s", field, MFSqlBase.LESS, arg);
                case GT:
                    return String.format("%s %s %s", field, MFSqlBase.MORE, arg);
                case LE:
                    return String.format("%s %s %s", field, MFSqlBase.LESS + MFSqlBase.EQUAL, arg);
                case GE:
                    return String.format("%s %s %s", field, MFSqlBase.MORE + MFSqlBase.EQUAL, arg);
                default:
                    throw new Exception("error condition and type");
            }
        }

    }

    public String toWhereSQL() {
        MFStringBuilder bs = new MFStringBuilder();
        boolean bfirst = true;
        for (Map.Entry<String, MFSqlWhereType> item : whereList.entrySet()) {
            if (bfirst) {
                bs.append(item.getKey());
                bfirst = false;
                continue;
            }

            switch (item.getValue()) {
                case AND:
                    bs.append(MFSqlBase.SPACE + MFSqlBase.AND + MFSqlBase.SPACE + item.getKey());
                    break;
                case OR:
                    bs.append(MFSqlBase.SPACE + MFSqlBase.OR + MFSqlBase.SPACE + item.getKey());
                    break;
                case NONE:
                    bs.append(MFSqlBase.SPACE + item.getKey());
                    break;
            }
        }
        return bs.toString();
    }

}
